/**
 * @file example_009.cpp
 * @author 逆流 (1171267147@qq.com)
 * @brief CRTP--静态多态
 * @version 1.0
 * @date 2025-07-14
 * 
 * @copyright Copyright (c) 2025
 * 
 */
#include <iostream>

using std::cout;

// template <typename Derived, typename SFINAE = std::enable_if_t<std::is_base_of_v<Base<Derived>, Derived>>>
// !实例化Derived时，Derived依赖Base<Derived>，而Base<Derived>又依赖Derived，导致递归实例化失败
// template <typename Derived, typename SFINAE = decltype(std::declval<Derived>().print())>
// !Derived 依赖Base<Derived>，而实例化Base<Derived>时，Derived尚未完整定义，无法访问print，导致定义失败
template <typename Derived>
class Base {
public:
    void print() {
        // 通过模板参数，获取子类对象的类型，实现函数的静态绑定
        static_cast<Derived*>(this)->print();
    }
};

class Derived : public Base<Derived> {
public:
    void print() { cout << "Derived " << a_ << '\n'; }

private:
    int a_ = 1;
};

class Derived2 : public Base<Derived2> {
public:
    void print() { cout << "Derived2 " << a_ << '\n'; }

private:
    int a_ = 2;
};

int main() {
    Derived  d;
    Derived2 d2;
    d.print();
    d2.print();

    Base<Derived>* b = &d;
    b->print();  // output: Derived 1

    Base<Derived2>* b2 = &d2;
    b2->print();  // output: Derived2 2

    Base<Derived> c;
    c.print();  // output: Base 364
    // 分析：非虚函数与普通函数一样，存在代码段，通过静态绑定。所以虽然c是Base类型，其print函数仍然可以通过static_cast转换，去调用Derived的print函数
    // 但是c的内存布局还是Base类型，因此输出的是随机值

    return 0;
}
